﻿using NHibernate;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using NHibernate.Linq;
using JuCloudy.Data.Entity;

namespace JuCloudy.Data.Nhibernate
{
    public class AuthenticationContainer 
    {
        private static global::NHibernate.Cfg.Configuration mCfg = null;
        private static global::NHibernate.ISessionFactory SessionFactory = null;

        public AuthenticationContainer()
        {
            mCfg = new NHibernate.Cfg.Configuration().Configure(
               System.Web.HttpContext.Current.Server.MapPath(
                    System.Configuration.ConfigurationManager.AppSettings["AuthNhCfg"]
                    ));

            SessionFactory = null;

            mCfg.AddClass(typeof(JuCloudy.Data.Entity.SsoMembership));
            mCfg.AddClass(typeof(JuCloudy.Data.Entity.SsoUserInfo));
            SessionFactory = mCfg.BuildSessionFactory();
        }

        //根据MemberId获得memberInfo
        public Data.Entity.SsoMembership GetMemberInfo(String MemberId)
        {
            using (ISession session = SessionFactory.OpenSession())
            {
                try
                {
                    var query = session.Query<JuCloudy.Data.Entity.SsoMembership>().First(p => p.MemberId == MemberId);
                    session.Flush();
                    session.Close();
                    session.Dispose();
                    if (query != null)
                        return query;
                    else
                        return null;
                }
                catch
                {
                    return null;
                }
            }
        }
        //根据UserName获得MemberInfo
        public Data.Entity.SsoMembership GetMemberInfoByUserName(String UserName)
        {
            using (ISession session = SessionFactory.OpenSession())
            {
                try
                {
                    var query = session.Query<JuCloudy.Data.Entity.SsoMembership>().First(p => p.Username == UserName);
                    session.Flush();
                    session.Close();
                    session.Dispose();
                    if (query != null)
                        return query;
                    else
                        return null;
                }
                catch
                {
                    return null;
                }
            }
        }
        //根据UserId获得UserInfo
        public Data.Entity.SsoUserInfo GetUserInfo(int UserId)
        {
            using (ISession session = SessionFactory.OpenSession())
            {
                try
                {
                    var query = session.Query<JuCloudy.Data.Entity.SsoUserInfo>().First(p => p.UserId == UserId);
                    session.Flush();
                    session.Close();
                    session.Dispose();
                    return query;
                }
                catch { return null; }
            }
        }
        //根据UserName获得UserInfo
        public Data.Entity.SsoUserInfo GetUserInfoByUserName(String UserName)
        {
            using (ISession session = SessionFactory.OpenSession())
            {
                try
                {
                    var query = session.Query<JuCloudy.Data.Entity.SsoUserInfo>().First(p => p.UserName == UserName);
                    session.Flush();
                    session.Close();
                    session.Dispose();
                    return query;
                }
                catch { return null; }
            }
        }
        //根据UserId和Password验证用户身份
        public AuthResult Auth(int UserId, String Password)
        {
            var UserInfo = GetUserInfo(UserId);
            if (UserInfo == null)
            {
                return AuthResult.UserNotExsit;
            }

            else
            {
                return AuthByUserName(UserInfo.UserName, Password);
            }
        }
        //根据UserName和Password验证用户身份
        public AuthResult AuthByUserName(String UserName, String Password)
        {
            try
            {
                var member = GetMemberInfoByUserName(UserName);
                if (member == null)
                {
                    return AuthResult.UserNotExsit;
                }
                RsaContainer rsa = new RsaContainer();
                String Correctpwd = rsa.DecryptByRsaId(member.Hash);
                int MaxLoginFailureTimes = int.Parse(System.Configuration.ConfigurationManager.AppSettings["MaxLoginFailureTimes"]);

                if (member.IsLocked)//用户锁定
                    return AuthResult.Locked;
                else if(MaxLoginFailureTimes!=0&&member.LoginFailedTimes>=MaxLoginFailureTimes)//失败次数超限
                {
                    return AuthResult.FailuresLimits;
                }
                else if (String.IsNullOrEmpty(Correctpwd))//密码不存在
                {
                    return AuthResult.NoPassword;
                }
                else if (member.PasswordExpiredDate <= DateTime.Now)//密码失效
                {
                    return AuthResult.PasswordExpired;
                }
                else if (Password != Correctpwd)//密码不正确
                {
                    return AuthResult.Correct;
                }
                else//登录成功
                {
                    return AuthResult.Success;
                }
            }
            catch
            {
                return AuthResult.Failed;//内部错误
            }
        }
        //新增用户
        public void CreateNewUser(Entity.SsoUserInfo UserInfo, String IpAddress)
        {
            Entity.SsoMembership member = new Entity.SsoMembership();
            member.CreateDate = DateTime.Now;
            member.EMail = UserInfo.EMail;
            member.Hash = String.Empty;
            member.IpAddress = IpAddress;
            member.IsLocked = false;
            member.MemberId = Guid.NewGuid().ToString();
            member.Telphone = UserInfo.Telphone;

            using (NHibernate.ISession session = SessionFactory.OpenSession())
            {
                using (NHibernate.ITransaction vTransaction = session.BeginTransaction())
                {
                    try
                    {
                        session.Save(member);
                        session.Save(UserInfo);
                        vTransaction.Commit();
                        vTransaction.Dispose();
                        session.Flush();
                        session.Close();
                        session.Dispose();
                    }
                    catch (Exception ex)
                    {
                        vTransaction.Rollback();
                        vTransaction.Dispose();
                        session.Flush();
                        session.Close();
                        session.Dispose();
                        throw ex;
                    }
                }
            }
        }
        //设置密码
        public void SetPassword(String MemberId, String Password, String IpAddress)
        {
            Double PasswordExpiredDays = Double.Parse(System.Configuration.ConfigurationManager.AppSettings["PasswordExpiredDays"]);

            var member = GetMemberInfo(MemberId);
            RsaContainer rsa = new RsaContainer();
            String PK = String.Empty;
            String RsaId = rsa.GeneralKey(IpAddress, out PK);
            rsa.Encrypt(RsaId, PK, Password, IpAddress);
            member.Hash = RsaId;
            member.LastPasswordChangedDate = DateTime.Now;
            if (member.PasswordChangedTimes == null)
                member.PasswordChangedTimes = 1;
            else
                member.PasswordChangedTimes = member.PasswordChangedTimes + 1;

            if (PasswordExpiredDays == 0)
                member.PasswordExpiredDate = DateTime.MinValue;
            else
                member.PasswordExpiredDate = DateTime.Now.AddDays(PasswordExpiredDays);

            using (NHibernate.ISession session = SessionFactory.OpenSession())
            {
                using (NHibernate.ITransaction vTransaction = session.BeginTransaction())
                {
                    try
                    {
                        session.SaveOrUpdate(member);
                        vTransaction.Commit();
                        vTransaction.Dispose();
                        session.Flush();
                        session.Close();
                        session.Dispose();
                    }
                    catch (Exception ex)
                    {
                        vTransaction.Rollback();
                        vTransaction.Dispose();
                        session.Flush();
                        session.Close();
                        session.Dispose();
                        throw ex;
                    }
                }
            }

        }
        //根据UserId设置密码
        public void SetPasswordByUserId(int UserId, String Password, String IpAddress)
        {
            var UserInfo = GetUserInfo(UserId);
            var member = GetMemberInfoByUserName(UserInfo.UserName);
            SetPassword(member.MemberId, Password, IpAddress);
        }
        //检测用户是否已存在
        public bool UserNameExsit(String UserName)
        {
            var UserInfo = GetUserInfoByUserName(UserName);
            if (UserInfo != null)
            {
                return true;
            }
            else { return false; }
        }
        //检测电子邮箱是否已存在
        public bool EmailExsit(String Email)
        {
            using (ISession session = SessionFactory.OpenSession())
            {
                try
                {
                    var query = session.Query<JuCloudy.Data.Entity.SsoUserInfo>().First(p => p.EMail == Email);
                    session.Flush();
                    session.Close();
                    session.Dispose();
                    if (query != null)
                    {
                        return true;
                    }
                    else
                    {
                        return false;
                    }
                }
                catch { return false; }
            }
        }
        //检测手机号码是否已存在
        public bool TelPhoneExsit(String TelPhone)
        {
            using (ISession session = SessionFactory.OpenSession())
            {
                try
                {
                    var query = session.Query<JuCloudy.Data.Entity.SsoUserInfo>().First(p => p.Telphone == TelPhone);
                    session.Flush();
                    session.Close();
                    session.Dispose();
                    if (query != null)
                    {
                        return true;
                    }
                    else
                    {
                        return false;
                    }
                }
                catch { return false; }
            }
        }
        //重置密码
        public void ReSetPassword(String memberId)
        {
            var member = GetMemberInfo(memberId);
            member.PasswordExpiredDate = DateTime.Now;
            using (NHibernate.ISession session = SessionFactory.OpenSession())
            {
                using (NHibernate.ITransaction vTransaction = session.BeginTransaction())
                {
                    try
                    {
                        session.SaveOrUpdate(member);
                        vTransaction.Commit();
                        vTransaction.Dispose();
                        session.Flush();
                        session.Close();
                        session.Dispose();
                    }
                    catch (Exception ex)
                    {
                        vTransaction.Rollback();
                        vTransaction.Dispose();
                        session.Flush();
                        session.Close();
                        session.Dispose();
                        throw ex;
                    }
                }
            }
        }
        //通过UserId重置密码
        public void ReSetPasswordByUserId(int UserId)
        {
            var userinfo = GetUserInfo(UserId);
            var member = GetMemberInfoByUserName(userinfo.UserName);
            ReSetPassword(member.MemberId);
        }
        //连接验证过程
        public AuthResult Connect(String UserName)
        {
            var member = GetMemberInfoByUserName(UserName);
            if (member.IsLocked)
                return AuthResult.Locked;
            else
                return AuthResult.Success;
        }
        //连接登陆过程
        public AuthResult Login(String UserName, String Password,String IpAddress,out String UserInfo)
        {
            var result = AuthByUserName(UserName, Password);
            if (result == AuthResult.Success)
            {
                LoginSuccess(UserName, IpAddress);
                UserInfo = GetUserInfoByUserName(UserName).Serialize();
            }
            else
            {
                LoginFailed(UserName);
                UserInfo = null;
            }

            return result;
        }
        //登录失败时执行
        private void LoginFailed(String UserName)
        {
            var member = GetMemberInfoByUserName(UserName);
            member.LastLoginFailedDatetime = DateTime.Now;
            if (member.LoginFailedTimes == null)
                member.LoginFailedTimes = 1;
            else
                member.LoginFailedTimes = member.LoginFailedTimes + 1;

            using (NHibernate.ISession session = SessionFactory.OpenSession())
            {
                using (NHibernate.ITransaction vTransaction = session.BeginTransaction())
                {
                    try
                    {
                        session.SaveOrUpdate(member);
                        vTransaction.Commit();
                        vTransaction.Dispose();
                        session.Flush();
                        session.Close();
                        session.Dispose();
                    }
                    catch (Exception ex)
                    {
                        vTransaction.Rollback();
                        vTransaction.Dispose();
                        session.Flush();
                        session.Close();
                        session.Dispose();
                        throw ex;
                    }
                }
            }
        }

        //登录成功时执行
        private void LoginSuccess(String UserName,String IpAddress)
        {
            var Userinfo = GetUserInfoByUserName(UserName);
            Userinfo.LastLoginDate = DateTime.Now;
            Userinfo.LastLoginIpAddress = IpAddress;
            if (Userinfo.LoginTimes == null)
                Userinfo.LoginTimes = 1;
            else
                Userinfo.LoginTimes = Userinfo.LoginTimes + 1;

            var member = GetMemberInfoByUserName(UserName);
            member.LoginFailedTimes = 0;

            using (NHibernate.ISession session = SessionFactory.OpenSession())
            {
                using (NHibernate.ITransaction vTransaction = session.BeginTransaction())
                {
                    try
                    {
                        session.SaveOrUpdate(Userinfo);
                        session.SaveOrUpdate(member);
                        vTransaction.Commit();
                        vTransaction.Dispose();
                        session.Flush();
                        session.Close();
                        session.Dispose();
                    }
                    catch (Exception ex)
                    {
                        vTransaction.Rollback();
                        vTransaction.Dispose();
                        session.Flush();
                        session.Close();
                        session.Dispose();
                        throw ex;
                    }
                }
            }
        }

       
    }
}
